#!/usr/bin/env python

# Copyright (C) 2010 Zajcev Evgeny <zevlg@yandex.ru>

# Ad-hoc OSM files generator
# Use -s to generate eb8 files

import sys, getopt, string
import operator as op
import functools as func
import random as rnd

map(sys.path.append, ["./", "../", "../src"])

from osmtrunc import __version__
from osmt import make_polygon

HEAD = """<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="Osmtrunc v%s">"""%__version__
TAIL = "</osm>"
N = 10000

def usage():
    print "usage: %s [-s] [-n <N>] <poly-file> <out-file>"%sys.argv[0]
    print "<poly-file> - Polygon file"
    print "<out-file>  - File to write OSM to"
    print "\t-n <N>\tNumber of tags to generate (default: %d)"%N
    print "\t-s\tShuffle nodes, ways and relations (results in eb8 file)"
    sys.exit(0)

try:
    opts, sargs = getopt.getopt(sys.argv[1:], "sn:")
except getopt.GetoptError, err:
    print str(err)
    usage()
if len(sargs) != 2:
    usage()

sflag = False
for o,v in opts:
    if o == "-n":
        N = int(v)
    elif o == "-s":
        sflag = True

POLY = make_polygon(sargs[0])
OUT = open(sargs[1], "w")

BBOX = POLY.bounds()
XRNG = BBOX[2]-BBOX[0]
YRNG = BBOX[3]-BBOX[1]

NDRANGE = (2,100)
MBRANGE = (3,200)

TTNAMES = ["node", "way", "relation"]
TTDISTRIB = zip(TTNAMES, [0.7, 0.2, 0.1])
INCIDS = dict(zip(TTNAMES, [set() for tt in TTNAMES]))
INCPROBS = dict(zip(TTNAMES, [0.1, 0.1, 0.5]))

IDRINC = (100, 2**30)
IDNINC = (2**30, 2**31)

def randttype():
    """Return random type according to tag types distribution."""
    rv = rnd.random()
    v = 0
    for i in TTDISTRIB:
        v += i[1]
        if rv < v:
            return i[0]
    raise Exception("Invalid TTDISTRIB")

def randid(r):
    return apply(rnd.randint, r)

def randstr(mlen=10):
    return "".join(rnd.sample(string.letters, mlen))

def incp(ttype):
    """Return True if TTYPE node should be included to output."""
    return rnd.random() < INCPROBS[ttype]

def gennode():
    FMT_NODE = '  <node id="%d" lat="%f" lon="%f" version="%d"/>'
    la, lo = BBOX[0] + rnd.random()*XRNG, BBOX[1]+rnd.random()*YRNG
    if POLY.is_inside(lo, la):
        nid = randid(IDRINC)
        INCIDS["node"].add(nid)
    else:
        nid = randid(IDNINC)
    return FMT_NODE%(nid, la, lo, rnd.randint(1,100))

def genway():
    nid = randid(IDNINC)
    FMT_WAY = '  <way id="%d" version="%d">'
    FMT_ND =  '    <nd ref="%d"/>'
    winc = incp("way") if len(INCIDS["node"]) else False
    rwinc = False
    res = []
    ndr = apply(rnd.randint, NDRANGE)
    for i in xrange(ndr):
        if winc and rnd.randint(0, ndr) < 3:
            ref = rnd.choice(list(INCIDS["node"]))
            rwinc = True
        else:
            ref = randid(IDNINC)
        res.append(FMT_ND%ref)
    if rwinc:
        nid = randid(IDRINC)
        INCIDS["way"].add(nid)
    res.insert(0, FMT_WAY%(nid, rnd.randint(1,100)))
    res.append("  </way>")
    return "\n".join(res)

def genrelation():
    nid = randid(IDNINC)
    FMT_REL = '  <relation id="%d" version="%d">'
    FMT_MBR = '    <member type="%s" ref="%d"/>'
    FMT_TAG = '    <tag k="%s" v="%s"/>'
    minc = incp("relation") if any(map(len, INCIDS.values())) else False
    rminc = False
    res = []
    mbr = apply(rnd.randint, MBRANGE)
    for i in xrange(mbr):
        rndr = rnd.randint(0, mbr)
        if rndr < mbr/4:
            res.append(FMT_TAG%(randstr(), randstr(rndr%30)))
            continue

        rt = "node"
        ref = randid(IDNINC)
        if minc:
            for tn in TTNAMES:
                if rndr < TTNAMES.index(tn)+1 and len(INCIDS[tn]):
                    rt = tn
                    ref = rnd.choice(list(INCIDS[tn]))
                    rminc = True
        res.append(FMT_MBR%(rt, ref))
    if rminc:
        nid = randid(IDRINC)
        INCIDS["relation"].add(nid)
    res.insert(0, FMT_REL%(nid, rnd.randint(1,100)))
    res.append("  </relation>")
    return "\n".join(res)
    
def gentag(ttype):
    return eval("gen%s()"%ttype)

def genosm(N):
    print >> OUT, HEAD
    tags = [gentag(randttype()) for i in xrange(N)]
    if sflag:
        rnd.shuffle(tags)
    for t in tags:
        print >> OUT, t
    print >> OUT, TAIL

print "+ Patience please.. "
genosm(N)
OUT.close()
print "+ For saving: %s"%", ".join(map(lambda x: "%s: %d"%(x, len(INCIDS[x])), INCIDS))
